package main;

import java.util.ArrayList;
import java.util.Date;

import problemSpace.ConcretePlanning;
import problemSpace.Delivery;
import problemSpace.Order;
import problemSpace.Station;
import problemSpace.Vehicle;
import problemSpace.timeInterval;

public class HelperFunctions {
	
	/**
	 * Checks the given concrete planning for uncompleted orders and schedules them
	 */
	public static void rescheduleOrders(ConcretePlanning cp){
		for(int i = 0; i<cp.orders.size();){
			Order anOrder = cp.orders.get(i);
			Delivery delivery = anOrder.addVehicle(cp.vehicles, cp.stations);
			if (delivery != null) {
				cp.output.resultList.get(cp.output.resultList.size() - 1).deliveries.add(delivery);
			}
			if (anOrder.failedTries > (cp.vehicles.size() * 2)) {
				anOrder.failedTries = 0;
				if(anOrder.lastLoadingStop == null)	anOrder.lastLoadingStop = anOrder.from;
				anOrder.from = new Date(anOrder.from.getTime() + 60000);
				// System.out.println("OPGELET Order wordt 1 minuut te laat geleverd !!");
			}
			// System.out.println("Gedaan!");

			// ga naar de volgende order met remaining volume
			if(anOrder.remainingVolume<=0){
				if(anOrder.lastLoadingStop != null)anOrder.from = anOrder.lastLoadingStop;
				i++;
			}
		} 
	}

	/**
	 * Unschedules the given order but doesn't delete it. (resets
	 * remainingVolume, removes deliveries and removes timeIntervals from
	 * stations and vehicles)
	 * @return Reference to the order that was undone.
	 */
	public static Order undoOrder(ConcretePlanning s, Order order) {
		order.remainingVolume = order.totalVolumeM3;
		int vehicleIntervalsDeleted = 0, stationIntervalDeleted = 0, deliveriesDeleted = 0;
		for(Vehicle veh : s.vehicles){
			vehicleIntervalsDeleted += veh.removeTimeInterval(order.orderCode);
		}
		for(Station sta : s.stations){
			stationIntervalDeleted += sta.removeTimeInterval(order.orderCode);
		}
		
		ArrayList<Delivery> deliveries = s.output.resultList.get(s.output.resultList.size()-1).deliveries;
		
		for(int i=deliveries.size()-1;i>=0;i--){
			Delivery del = deliveries.get(i);
			if(del.orderCode.equals(order.orderCode)) {
				if(deliveries.remove(i) != null) deliveriesDeleted++;
			}
		}
		if (vehicleIntervalsDeleted != deliveriesDeleted) {
			System.out.print(" intervals deleted " + vehicleIntervalsDeleted);
			System.out.println("\t" + deliveriesDeleted + " deliveriesDeleted");
		}
		if (vehicleIntervalsDeleted != stationIntervalDeleted)
			System.out.println("vehicleIntervalsDeleted != stationIntervalDeleted");

		return order;
	}
	
	public static void undoVehicle(ConcretePlanning s, Vehicle v){
		String oCode;
		Order order;
		for(timeInterval interval : v.occupied){
			oCode = interval.orderCode;
			order = s.getOrderByCode(oCode);
			removeStationInterval(interval, s);
			removeDelivery(interval, s,order);
		}
		v.occupied.clear();
	}
	public static void removeStationInterval(timeInterval interval, ConcretePlanning s){
		timeInterval tempInterval = null;
		for(Station sta : s.stations){
			for(timeInterval interval2 : sta.occupied){
				if(interval2.orderCode.equals(interval.orderCode)
						&& interval2.getStart().equals(interval.getStart())
						&& interval2.getEnd().equals(interval.getEnd())){
					tempInterval = interval2;
					break;
				}
			}
			sta.occupied.remove(tempInterval);
			break;
		}
	}
	public static void removeDelivery(timeInterval interval,ConcretePlanning s, Order order){
		ArrayList<Delivery> deliveries = s.output.resultList.get(s.output.resultList.size()-1).deliveries;
		Delivery deli = null;
		for(Delivery d : deliveries){
			if(d.orderCode.equals(interval.orderCode)
					&& d.loadingTime.equals(interval.getStart())
					&& d.unloadingTime.equals(interval.getEnd())){
				deli = d;
				break;
			}
		}
		if(deli!=null){
			if(order.remainingVolume<0)
				order.remainingVolume=0;
			order.remainingVolume += deli.volume;
			deliveries.remove(deli);
		}
	}

}
